/*    
    OpenMheg - A free MHEG-5 library
    Copyright (C) 2008 Dharmesh Malam

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Text;

using Core.Model.Events;
using Core.Model.Data.Variables;
using Core.Model.Data.Type;
using Engine;
using Core.Model.Ingredients;

namespace Core.Model
{
    public abstract class Root 
    {
        protected  readonly log4net.ILog log ;

        public Root ()
        {
            log = log4net.LogManager.GetLogger( this.GetType() );
        }

        #region Exchanged Attributes
        private ObjectRef objectIdentifier;

        public ObjectRef ObjectIdentifier
        {
            get { return objectIdentifier; }
            set { objectIdentifier = value; }
        }

        #endregion

        #region Internal Attributes

        private bool availabilityStatus = false;
        private bool runningStatus = false;

        internal bool AvailabilityStatus
        {
            get { return availabilityStatus; }
            set { availabilityStatus = value; }
        }


        public bool RunningStatus
        {
            get { return runningStatus; }
            set { runningStatus = value; }
        }

        public virtual void InittInternalAttributes ()
        {
        }

        #endregion

        #region  Event link collections

        //private List<Link> isAvailable = new List<Link>();
        //internal List<Link> IsAvailable
        //{
        //    get { return isAvailable; }
        //    set { IsAvailable = value; }
        //}

        //private List<Link> contentAvailable = new List<Link>();
        //internal List<Link> ContentAvailable
        //{
        //    get { return contentAvailable; }
        //    set { contentAvailable = value; }
        //}

        //private List<Link> isDeleted = new List<Link>();
        //internal List<Link> IsDeleted
        //{
        //    get { return isDeleted; }
        //    set { isDeleted = value; }
        //}

        //private List<Link> isRunning = new List<Link>();
        //internal List<Link> IsRunning
        //{
        //    get { return isRunning; }
        //    set { isRunning = value; }
        //}

        //private List<Link> isStopped = new List<Link>();
        //internal List<Link> IsStopped
        //{
        //    get { return isStopped; }
        //    set { isStopped = value; }
        //}

        #endregion

        #region Internal  Members
        
        public virtual void Prepare ()
        {
            if ( AvailabilityStatus )
                return;

            InittInternalAttributes();

            AvailabilityStatus = true;

            //  Preparation behaviour complete
            Engine.MHEGEngine.Instance.Handle( new IsAvailable( this ) );

            //async
            if ( this is Ingredient )
            {
                Ingredient ingredient = ( Ingredient ) this;
                if( ingredient.Content != null && !ingredient.Content.IsEmpty())
                    Engine.MHEGEngine.Instance.AsyncHandle( new ContentAvailable( this ) );
            }
            else
            Engine.MHEGEngine.Instance.AsyncHandle( new ContentAvailable( this ) );
        }

        public virtual void Destroy ()
        {
            if ( !AvailabilityStatus )
                return;

            if ( RunningStatus )
                Deactivate();

            AvailabilityStatus = false;
            
            //  Destruction behaviour complete
            Engine.MHEGEngine.Instance.Handle( new IsDeleted( this ) );
        }

        public virtual void Activate ()
        {
            if ( RunningStatus )
                return;

            if ( !AvailabilityStatus )
                Prepare();

            //RunningStatus = true;

            //Engine.MHEGEngine.Instance.Handle( new IsRunning( this ) );
        }

        public virtual void Deactivate ()
        {
            if ( !RunningStatus )
                return;

            RunningStatus = false;

            Engine.MHEGEngine.Instance.Handle( new IsStopped( this ) );
        }

        #endregion

        #region Actions
        public void GetAvailabilityStatus ( BooleanVariable availabilityStatusVar)
        {
            if ( availabilityStatusVar!= null )
                availabilityStatusVar.Value = AvailabilityStatus;
        }

        public void GetRunningStatus ( BooleanVariable runningStatusVar )
        {
            if ( runningStatusVar != null )
                runningStatusVar.Value = RunningStatus;
        }



        #endregion

        #region Event processing
        //public virtual void handle ( Events.Event evnt )
        //{
        //    switch ( evnt.Type )
        //    {
        //        case Events.enumEvents.IsAvailable:
        //            foreach ( Link l in IsAvailable )
        //                l.fire();
        //            break;

        //        case Events.enumEvents.ContentAvailable:
        //            foreach ( Link l in ContentAvailable )
        //                l.fire();
        //            break;

        //        case Events.enumEvents.IsDeleted:
        //            foreach ( Link l in IsDeleted )
        //                l.fire();
        //            break;

        //        case Events.enumEvents.IsRunning:
        //            foreach ( Link l in IsRunning )
        //                l.fire();
        //            break;

        //        case Events.enumEvents.IsStopped:
        //            foreach ( Link l in IsStopped )
        //                l.fire();
        //            break;

        //        default:
        //            throw new Exception( "Unknown Event" );
        //        //log.warning("Unhandled event " + evnt.Type + " passed to Root; should be handled by an extending class!");
        //            break;
        //    }
        //}

        //public virtual void addLink ( Link link )
        //{
        //    if ( link.LinkCondition.EventSource.Equals( objectIdentifier ) )
        //    {
        //        switch ( link.LinkCondition.EventType )
        //        {
        //            case Events.enumEvents.IsAvailable:
        //                isAvailable.Add( link );
        //                break;

        //            case Events.enumEvents.ContentAvailable:
        //                contentAvailable.Add( link );
        //                break;

        //            case Events.enumEvents.IsDeleted:
        //                isDeleted.Add( link );
        //                break;

        //            case Events.enumEvents.IsRunning:
        //                isRunning.Add( link );
        //                break;

        //            case Events.enumEvents.IsStopped:
        //                isStopped.Add( link );
        //                break;
        //        }
        //    }
        //    else
        //    {
        //        throw new Exception( "Unknown Link" );
        //        // log.warning("Supplied link's event source did not match this object");
        //    }
        //}
        #endregion


        public override string ToString ()
        {
            return GetType().ToString() + ":" + objectIdentifier.ToString();
        }
    }
}
